package com.world.core;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ServiceManager {
    private static Logger logger = LoggerFactory.getLogger(ServiceManager.class);

    private static ListableBeanFactory factory;

    private static final Map<Object, Object> cache = new ConcurrentHashMap<Object, Object>();

    public static void setApplicationContext(ListableBeanFactory factory) {
        ServiceManager.factory = factory;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static <T> T getBeanByClass(Class<T> clazz) {
        try {
            return (T) getService(clazz.getName());
        } catch (NoSuchBeanDefinitionException e) {
            Map clazzes = factory.getBeansOfType(clazz);
            for (Iterator i$ = clazzes.values().iterator(); i$.hasNext(); ) {
                Object entry = i$.next();
                if (clazz.isInterface()) {
                    Class[] interfaces = entry.getClass().getInterfaces();
                    for (Class c : interfaces) {
                        if (c.isAssignableFrom(clazz))
                            return (T) entry;
                    }
                } else if (clazz.isAssignableFrom(entry.getClass())) {
                    return (T) entry;
                }
            }
            throw new NoSuchBeanDefinitionException(clazz, "ServiceManager can not find bean !");
        } finally {

        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T getService(Class<T> clazz) {
        T service = (T) cache.get(clazz);
        if (service != null) {
            return service;
        }
        service = getBeanByClass(clazz);
        cache.put(clazz, service);
        return service;
    }

    public static Object getService(String id) {
        Object obj = cache.get("__name__" + id);
        if (obj != null) {
            return obj;
        }
        obj = getBeanByName(id);
        cache.put("__name__" + id, obj);
        return obj;
    }

    private static Object getBeanByName(String id) {
        if (logger.isDebugEnabled()) {
            logger.debug(" ServiceManager lookup service id = '" + id + "'");
        }
        Object o = factory.getBean(id);
        if (logger.isDebugEnabled()) {
            logger.debug(" return service object:" + o);
        }
        return o;
    }


}
